home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / fax / src / util / PageSize.c++ < prev    next >
C/C++ Source or Header  |  1994-08-01  |  7KB  |  285 lines

  1. /*    $Header: /usr/people/sam/fax/util/RCS/PageSize.c++,v 1.13 1994/02/28 14:24:16 sam Rel $ */
  2. /*
  3.  * Copyright (c) 1993, 1994 Sam Leffler
  4.  * Copyright (c) 1993, 1994 Silicon Graphics, Inc.
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and 
  7.  * its documentation for any purpose is hereby granted without fee, provided
  8.  * that (i) the above copyright notices and this permission notice appear in
  9.  * all copies of the software and related documentation, and (ii) the names of
  10.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  11.  * publicity relating to the software without the specific, prior written
  12.  * permission of Sam Leffler and Silicon Graphics.
  13.  * 
  14.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  15.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  16.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  17.  * 
  18.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  19.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  20.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  21.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  22.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  23.  * OF THIS SOFTWARE.
  24.  */
  25. /*
  26.  * Page Size Support.
  27.  */
  28. #include "Types.h"
  29. #include "PageSize.h"
  30. #include "Array.h"
  31. #include "config.h"
  32.  
  33. #include <string.h>
  34. #include <ctype.h>
  35. #include <stdlib.h>
  36.  
  37. fxDECLARE_StructArray(PageInfoArray, PageInfo);
  38. fxIMPLEMENT_StructArray(PageInfoArray, PageInfo);
  39.  
  40. PageInfoArray* PageSizeInfo::pageInfo = NULL;
  41.  
  42. #include <stdarg.h>
  43.  
  44. static void
  45. parseError(const char* file, u_int lineno, const char* fmt ...)
  46. {
  47.     va_list ap;
  48.     va_start(ap, fmt);
  49.     fprintf(stderr, "%s: line %u: ", file, lineno); 
  50.     vfprintf(stderr, fmt, ap);
  51.     va_end(ap);
  52. }
  53.  
  54. fxBool
  55. PageSizeInfo::skipws(char*& cp,
  56.     const char* file, const char* item, u_int lineno)
  57. {
  58.     if (isspace(*cp))
  59.     *cp++ = '\0';
  60.     while (isspace(*cp))
  61.     cp++;
  62.     if (*cp == '\0') {
  63.     parseError(file, lineno,
  64.         "Unexpected end of line after \"%s\".\n", item);
  65.     return (FALSE);
  66.     } else
  67.     return (TRUE);
  68. }
  69.  
  70. PageInfoArray*
  71. PageSizeInfo::readPageInfoFile()
  72. {
  73.     char file[1024];
  74.     sprintf(file, "%s/%s", FAX_LIBDATA, FAX_PAGESIZES);
  75.     PageInfoArray* info = new PageInfoArray;
  76.     FILE* fp = fopen(file, "r");
  77.     u_int lineno = 0;
  78.     if (fp) {
  79.     char line[1024];
  80.     while (fgets(line, sizeof (line), fp)) {
  81.         lineno++;
  82.         char* cp = strchr(line, '#');
  83.         if (cp)
  84.         *cp = '\0';
  85.         else if (cp = strchr(line, '\n'))
  86.         *cp = '\0';
  87.         for (cp = line; isspace(*cp); cp++)
  88.         ;
  89.         if (*cp == '\0')
  90.         continue;
  91.         // name<tab>width<ws>height<ws>gwidth<ws>gheight<ws>top<ws>left
  92.         PageInfo pi;
  93.         pi.name = cp;
  94.         while (*cp != '\t')
  95.         cp++;
  96.         if (!skipws(cp, file, "page size name", lineno))
  97.         continue;
  98.         pi.abbr = cp;
  99.         while (*cp != '\t')
  100.         cp++;
  101.         if (!skipws(cp, file, "page size abbreviation", lineno))
  102.         continue;
  103.         pi.w = (BMU) strtoul(cp, &cp, 10);
  104.         if (!skipws(cp, file, "page width", lineno))
  105.         continue;
  106.         pi.h = (BMU) strtoul(cp, &cp, 10);
  107.         if (!skipws(cp, file, "page height", lineno))
  108.         continue;
  109.         pi.grw = (BMU) strtoul(cp, &cp, 10);
  110.         if (!skipws(cp, file, "guaranteed page width", lineno))
  111.         continue;
  112.         pi.grh = (BMU) strtoul(cp, &cp, 10);
  113.         if (!skipws(cp, file, "guaranteed page height", lineno))
  114.         continue;
  115.         pi.top = (BMU) strtoul(cp, &cp, 10);
  116.         if (!skipws(cp, file, "top margin", lineno))
  117.         continue;
  118.         pi.left = (BMU) strtoul(cp, &cp, 10);
  119.         pi.name = strdup(pi.name);
  120.         pi.abbr = strdup(pi.abbr);
  121.         info->append(pi);
  122.     }
  123.     } else {
  124.     fprintf(stderr,
  125.     "Warning, no page size database file \"%s\", using builtin default.\n",
  126.         file);
  127.     PageInfo pi;
  128.     pi.name = strdup("default");
  129.     pi.abbr = strdup("NA-LET");
  130.     // North American Letter
  131.     pi.w = 10200;
  132.     pi.h = 13200;
  133.     pi.grw = 9240;
  134.     pi.grh = 12400;
  135.     pi.top = 472;
  136.     pi.left = 345;
  137.     info->append(pi);
  138.     }
  139.     fclose(fp);
  140.     return info;
  141. }
  142.  
  143. const PageInfo*
  144. PageSizeInfo::getPageInfoByName(const char* name)
  145. {
  146.     int c = tolower(name[0]);
  147.     size_t len = strlen(name);
  148.     for (int i = 0, n = pageInfo->length(); i < n; i++) {
  149.     for (const char* cp = (*pageInfo)[i].name; *cp != '\0'; cp++)
  150.         if (tolower(*cp) == c && strncasecmp(cp, name, len) == 0)
  151.         return &(*pageInfo)[i];
  152.     }
  153.     return (NULL);
  154. }
  155.  
  156. PageSizeInfo*
  157. PageSizeInfo::getPageSizeByName(const char* name)
  158. {
  159.     if (pageInfo == NULL)
  160.     pageInfo = readPageInfoFile();
  161.     const PageInfo* info = getPageInfoByName(name);
  162.     return info ? new PageSizeInfo(*info) : NULL;
  163. }
  164.  
  165. PageSizeInfo*
  166. PageSizeInfo::getPageSizeBySize(float wmm, float hmm)
  167. {
  168.     BMU w = fromMM(wmm);
  169.     BMU h = fromMM(hmm);
  170.  
  171.     if (pageInfo == NULL)
  172.     pageInfo = readPageInfoFile();
  173.     int best = 0;
  174.     u_long bestMeasure = (u_long)-1;
  175.     for (int i = 0, n = pageInfo->length(); i < n; i++) {
  176.     int dw = (int)((*pageInfo)[i].w - w);
  177.     int dh = (int)((*pageInfo)[i].h - h);
  178.     u_long measure = dw*dw + dh*dh;
  179.     if (measure < bestMeasure) {
  180.         best = i;
  181.         bestMeasure = measure;
  182.     }
  183.     }
  184. #define THRESHOLD 720000        // .5" in each dimension
  185.     return bestMeasure < THRESHOLD ? new PageSizeInfo((*pageInfo)[best]) : NULL;
  186. }
  187.  
  188. PageSizeInfo::PageSizeInfo()
  189. {
  190.     if (pageInfo == NULL)
  191.     pageInfo = readPageInfoFile();
  192.     info = getPageInfoByName("default");
  193. }
  194. PageSizeInfo::PageSizeInfo(const PageInfo& i) : info(&i) {}
  195. PageSizeInfo::~PageSizeInfo() {}
  196.  
  197. /*
  198.  * C stub interfaces...
  199.  */
  200. extern "C" struct pageSizeInfo*
  201. getPageSize(const char* name)
  202. {
  203.     return (struct pageSizeInfo*) PageSizeInfo::getPageSizeByName(name);
  204. }
  205.  
  206. extern "C" struct pageSizeInfo*
  207. closestPageSize(float w, float h)
  208. {
  209.     return (struct pageSizeInfo*) PageSizeInfo::getPageSizeBySize(w,h);
  210. }
  211.  
  212. extern "C" void
  213. delPageSize(struct pageSizeInfo* info)
  214. {
  215.     delete (PageSizeInfo*) info;
  216. }
  217.  
  218. extern "C" const char*
  219. getPageName(const struct pageSizeInfo* info)
  220. {
  221.      return ((const PageSizeInfo*) info)->name();
  222. }
  223.  
  224. extern "C" const char*
  225. getPageAbbrev(const struct pageSizeInfo* info)
  226. {
  227.      return ((const PageSizeInfo*) info)->abbrev();
  228. }
  229.  
  230. extern "C" float
  231. getPageWidth(const struct pageSizeInfo* info)
  232. {
  233.      return ((const PageSizeInfo*) info)->width();
  234. }
  235.  
  236. extern "C" float
  237. getPageHeight(const struct pageSizeInfo* info)
  238. {
  239.      return ((const PageSizeInfo*) info)->height();
  240. }
  241.  
  242. extern "C" float
  243. getPageGuarHeight(const struct pageSizeInfo* info)
  244. {
  245.      return ((const PageSizeInfo*) info)->guarHeight();
  246. }
  247.  
  248. extern "C" float
  249. getPageGuarWidth(const struct pageSizeInfo* info)
  250. {
  251.      return ((const PageSizeInfo*) info)->guarWidth();
  252. }
  253.  
  254. extern "C" float
  255. getPageTopMargin(const struct pageSizeInfo* info)
  256. {
  257.      return ((const PageSizeInfo*) info)->topMargin();
  258. }
  259.  
  260. extern "C" float
  261. getPageLeftMargin(const struct pageSizeInfo* info)
  262. {
  263.      return ((const PageSizeInfo*) info)->leftMargin();
  264. }
  265.  
  266. /*
  267.  * Page size iterator support.
  268.  */
  269.  
  270. PageSizeInfoIter::PageSizeInfoIter()
  271. {
  272.     i = 0;
  273. }
  274. PageSizeInfoIter::~PageSizeInfoIter()        {}
  275. void PageSizeInfoIter::operator++()        { i++; }
  276. void PageSizeInfoIter::operator++(int)        { i++; }
  277. PageSizeInfoIter::operator const PageSizeInfo&()
  278. {
  279.     if (i < PageSizeInfo::pageInfo->length())
  280.     pi.info = &(*PageSizeInfo::pageInfo)[i];
  281.     return (pi);
  282. }
  283. fxBool PageSizeInfoIter::notDone()
  284.     { return i < PageSizeInfo::pageInfo->length(); }
  285.